package dyyx.dto;

import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.Module;
import redis.clients.jedis.Tuple;
import redis.clients.jedis.util.Slowlog;

public class RedisClient{

	public final Jedis jedis;

	public final JedisCluster jedisCluster;

	public final String host;
	public final int port ;
	public final String pwd ;
	
	// jedis JedisCluster 
	public final String type ;
	
	
	public final static String TYPE_JEDIS = "jedis" ;

	public final static String TYPE_JEDIS_CLUSTER = "JedisCluster" ;



	public final String createTime ;
	
	private static boolean typeCheck(String type) {
		if(type==null) {
			return false;
		}
		if(TYPE_JEDIS.equalsIgnoreCase(type)) {
			return true;
		}
		if(TYPE_JEDIS_CLUSTER.equalsIgnoreCase(type)) {
			return true;
		}
		return false;
	}
	
	public RedisClient(String type,String host,int port,String pwd)throws Exception{

		
		
		if(StringUtils.isBlank(type)) {
			throw new Exception("type blank");
		}
		
		if(StringUtils.isBlank(host)) {
			throw new Exception("host blank");
		}
		
		if(!typeCheck(type)) {
			throw new Exception("type error");
		}
		
		this.type = type;
		this.host = host;
		this.port = port;
		this.pwd = pwd;
		
		if(TYPE_JEDIS.equalsIgnoreCase(type)) {
			Jedis jedistmp = new Jedis(host,port);	
			if(!StringUtils.isBlank(pwd)) {
				jedistmp.auth(pwd);
			}
			jedistmp.ping();
			this.jedis = jedistmp;
			this.jedisCluster = null;
		}else {
			this.jedis = null;
			this.jedisCluster = new JedisCluster(new HostAndPort(host,port));
		}
		

		
		this.createTime = LocalDateTime.now().toString();
		
	}
	
	
	public String info() {
		if(jedis!=null) {
			return jedis.info();
		}
		throw new RuntimeException("info not support,"+toString());
	}
	
	
	
	public String memoryDoctor() {
		if(jedis!=null) {
			return jedis.memoryDoctor();
		}
		throw new RuntimeException("memoryDoctor not support,"+toString());
		// return jedisCluster.memoryDoctor();
	}
	
	public List<Slowlog> slowlogGet() {
		if(jedis!=null) {
			return jedis.slowlogGet();
		}
		// jedisCluster.slowlogGet();
		throw new RuntimeException("info not support,"+toString());
	}
	
	public String clientList() {
		if(jedis!=null) {
			return jedis.clientList();
		}
		// jedisCluster.clientList();
		throw new RuntimeException("clientList not support,"+toString());
	}
	
	public List<Module>  moduleList() {
		if(jedis!=null) {
			return jedis.moduleList();
		}
		// jedisCluster.moduleList();
		throw new RuntimeException("moduleList not support,"+toString());
	}
	

	public String type(String key) {
		if(jedis!=null) {
			return jedis.type(key);
		}
		return jedisCluster.type(key);
	}
	

	public byte[] dump(String key) {
		if(jedis!=null) {
			return jedis.dump(key);
		}
		return jedisCluster.dump(key);
	}
	
	
	//
	
	public String clusterInfo() {
		if(jedis!=null) {
			return jedis.clusterInfo();
		}
		// return jedisCluster.clusterInfo();
		throw new RuntimeException("clusterInfo not support,"+toString());
	}
	
	public String clusterNodes() {
		if(jedis!=null) {
			return jedis.clusterNodes();
		}
		// return jedisCluster.clusterNodes();
		throw new RuntimeException("clusterNodes not support,"+toString());
		// Map<String, JedisPool> jedisPools = jedisCluster.getClusterNodes();	
	}
	
	
	
	public  List<String> clusterSlaves(String nodeId) {
		if(jedis!=null) {
			return jedis.clusterSlaves(nodeId);
		}
		// jedisCluster.clusterSlaves(nodeId);
		throw new RuntimeException("clusterSlaves not support,"+toString());
	}
	

	public  List<Object> clusterSlots() {
		if(jedis!=null) {
			return jedis.clusterSlots();
		}
		// jedisCluster.clusterSlots();
		throw new RuntimeException("clusterSlots not support,"+toString());
	}
	
	public  String asking() {
		if(jedis!=null) {
			return jedis.asking();
		}
		// jedisCluster.asking();
		throw new RuntimeException("asking not support,"+toString());
	}
	
	
	///
	
	public String get(String key) {
		if(jedis!=null) {
			return jedis.get(key);
		}
		return jedisCluster.get(key);
	}
	
	public List<String> lrange(String key,long start,long stop) {
		if(jedis!=null) {
			return jedis.lrange(key,start, stop);
		}
		return jedisCluster.lrange(key,start, stop);
	}
	
	public Long scard(String key) {
		if(jedis!=null) {
			return jedis.scard(key);
		}
		return jedisCluster.scard(key);
	}
	
	public Set<String> smembers(String key) {
		if(jedis!=null) {
			return jedis.smembers(key);
		}
		return jedisCluster.smembers(key);
	}
	
	public Long zcard(String key) {
		if(jedis!=null) {
			return jedis.zcard(key);
		}
		return jedisCluster.zcard(key);
	}
	
	
	
	public Map<String,String> hgetAll(String key) {
		if(jedis!=null) {
			return jedis.hgetAll(key);
		}
		return jedisCluster.hgetAll(key);
	}
	
	//
	public Long zcount(String key,double min,double max) {
		if(jedis!=null) {
			return jedis.zcount(key,min,max);
		}
		return jedisCluster.zcount(key,min,max);
	}
	
	
	// zrangeWithScores zrevrangeWithScores , zrangeByScoreWithScores zrevrangeByScoreWithScores
	
	public Set<Tuple> zrangeWithScores(String key, final long start, final long stop) {
		if(jedis!=null) {
			return jedis.zrangeWithScores(key,start,stop);
		}
		return jedisCluster.zrangeWithScores(key,start,stop);
	}
	
	
	public Set<Tuple> zrevrangeWithScores(String key, final long start, final long stop) {
		if(jedis!=null) {
			return jedis.zrevrangeWithScores(key,start,stop);
		}
		return jedisCluster.zrevrangeWithScores(key,start,stop);
	}
	
	public Set<Tuple> zrangeByScoreWithScores(final String key, final double min, final double max,
		      final int offset, final int count) {
		if(jedis!=null) {
			return jedis.zrangeByScoreWithScores(key,min, max,offset,count);
		}
		return jedisCluster.zrangeByScoreWithScores(key,min, max,offset,count);
	}
	
	
	public Set<Tuple> zrevrangeByScoreWithScores(final String key, final double min, final double max,
		      final int offset, final int count) {
		if(jedis!=null) {
			return jedis.zrevrangeByScoreWithScores(key,max, min,offset,count);
		}
		return jedisCluster.zrevrangeByScoreWithScores(key,max, min,offset,count);
	}
	
	
	////
	
	
	////
	
	@Override
	public String toString() {
		Map<String,String> map = new LinkedHashMap<>();
		map.put("type", type);
		map.put("host", host);
		map.put("port", port+"");

		map.put("createTime", createTime);


		return map.toString();
	}

}
